﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.WindowsAPICodePack.Taskbar;
using Microsoft.WindowsAPICodePack.Dialogs;
using System.Diagnostics;
using System.ComponentModel;
using System.Net;
using ArmoryData;
using ArmoryData.Character;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows.Threading;

namespace ArmoryViewer
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        static ProgressWindow pgs;
        System.Windows.Forms.NotifyIcon ni;
        BackgroundWorker bgwSearch = new BackgroundWorker();
        static bool searchBusy = true;
        ObservableCollection<Dictionary<string, string>> itemSource;


        /// <summary>
        /// Initializes a new instance of the <see cref="MainWindow"/> class.
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();
            AddSortBinding();
            AddNotifyIcon();
        }

        /// <summary>
        /// Creates the notification icon in the system tray.
        /// </summary>
        void AddNotifyIcon()
        {
            ni = new System.Windows.Forms.NotifyIcon();
            Stream iconStream = Application.GetResourceStream(new Uri("/ArmoryViewer;component/Resources/armoryViewer.ico", UriKind.Relative)).Stream;
            if (iconStream != null)
                ni.Icon = new System.Drawing.Icon(iconStream);
            ni.Visible = true;
            ni.DoubleClick += delegate(object sender, EventArgs e)
            {
                this.Show();
                this.WindowState = WindowState.Normal;
            };
        }

        /// <summary>
        ///  Sets the sorter for the ListView
        /// </summary>
        void AddSortBinding()
        {
            GridView gv = (GridView)lvwResults.View;
            for (int i = 1; i <= gv.Columns.Count; i++)
            {
                GridViewColumn col = gv.Columns[i - 1];
                ListViewSorter.SetSortBindingMember(col, new Binding(lvwResults.Name));
            }
            ListViewSorter.SetCustomSorter(lvwResults, new ResultSorter());
        }

        void CreateStatus()
        {
            pgs = new ProgressWindow();
        }

		private void Preferences_Click(object sender, System.Windows.RoutedEventArgs e)
        {
			PreferencesWindow win = new PreferencesWindow();
			win.ShowDialog();
        }
		
        private void MenuItem_Click(object sender, System.Windows.RoutedEventArgs e)
        {
        	Application.Current.Shutdown();
        }

        private void menuAbout_Click(object sender, RoutedEventArgs e)
        {
            AboutWindow win = new AboutWindow();
            win.Show();
        }

        private void winSearch_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            
        }
        
        private void btnSearch_Click(object sender, RoutedEventArgs e)
        {
            if (bgwSearch.IsBusy) return; // Don't try to search if already searching

            // If there's no text to search for then reset the list.
            if (txtQuery.Text == "")
            {
                lvwResults.ItemsSource = new List<Dictionary<string, string>>();
                return;
            }

            // Create background worker
            bgwSearch = new BackgroundWorker();
            bgwSearch.WorkerReportsProgress = true;
            bgwSearch.WorkerSupportsCancellation = true;
            bgwSearch.DoWork += new DoWorkEventHandler(bgwSearch_DoWork);
            bgwSearch.ProgressChanged += new ProgressChangedEventHandler(bgwSearch_ProgressChanged);
            bgwSearch.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgwSearch_RunWorkerCompleted);

            // Show the progress window
            CreateStatus();
            pgs = new ProgressWindow()
            {
                Title = "Searching",
                Text = "Searching for " + txtQuery.Text,
                ProgressState = TaskDialogProgressBarState.Marquee
            };
            pgs.TaskDialogClosing = SearchProgress_Closing;
            bgwSearch.RunWorkerAsync(new string[] { cboSearchType.SelectedIndex.ToString(), txtQuery.Text });
            pgs.ShowMe();
        }
        
        void SearchProgress_Closing(object sender, CancelEventArgs e)
        {
            if (searchBusy)
            {
                bgwSearch.CancelAsync();
                pgs.Text = "Cancelling...";
                e.Cancel = true;
            }
        }

        void bgwSearch_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        	try
        	{
	            searchBusy = false;
                if (pgs == null) return;
	            BackgroundWorker bgwSender = (BackgroundWorker)sender;
	            if (!bgwSender.CancellationPending) FillResults((List<Dictionary<string, string>>)e.Result);
	            bgwSender = new BackgroundWorker();
	            pgs.CloseDialog();
        	}
        	catch(Exception ex)
        	{
        		App.ShowErrorDialog(ex);
        	}
        }

        void bgwSearch_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.UserState is Exception)
            {
                pgs.CloseDialog();
                App.ShowErrorDialog(e.UserState as Exception);
            }
        }

        void FillResults(List<Dictionary<string, string>> results)
        {
            if (itemSource != null)
            {
                lvwResults.Items.SortDescriptions.Clear();
                ListViewSorter.SetCustomSorter(lvwResults, null);
                ListCollectionView view = (ListCollectionView)CollectionViewSource.GetDefaultView(lvwResults.ItemsSource);
                view.CustomSort = null;
            }

            if (results != null)
            {
                itemSource = new ObservableCollection<Dictionary<string, string>>(results);

                itemSource.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(itemSource_CollectionChanged);
                lvwResults.ItemsSource = itemSource;
                lvwResults.SelectedItems.Clear();
            }
            ListViewSorter.SetCustomSorter(lvwResults, new ResultSorter());
            FixColumnWidth(ref lvwResults);
            ListViewSorter.SortBy("Level", ListSortDirection.Descending);
        }

        void itemSource_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            throw new NotImplementedException();
        }

        void FixColumnWidth(ref ListView listView)
        {
            GridView view = listView.View as GridView;
            if (view == null) return;

            foreach(GridViewColumn col in view.Columns)
            {
                if (col.Header.ToString() == "Level") col.Width = 35;
                else
                {
                    col.Width = col.ActualWidth;
                    col.Width = Double.NaN;
                }
            }
        }

        void bgwSearch_DoWork(object sender, DoWorkEventArgs e)
        {
            searchBusy = true;
            BackgroundWorker bgwSender = (BackgroundWorker)sender;
            string[] args = (string[])e.Argument;
            string query = args[1];
            try
            {
                if (bgwSender.CancellationPending) return;
                switch (int.Parse(args[0]))
                {
                    case 1:
                        e.Result = Connector.GetSearchResults(Settings.ArmoryUrl, query, "characters");
                        break;
                    case 2:
                        e.Result = Connector.GetSearchResults(Settings.ArmoryUrl, query.Replace(" ", "+"), "guilds");
                        break;
                    case 0:
                        e.Result = Connector.GetSearchResults(Settings.ArmoryUrl, query.Replace(" ", "+"), "arenateams");
                        break;
                }
            }
            catch (WebException ex)
            {
                MessageBox.Show(ex.Message);

            }
            catch (Exception ex)
            {
                if (bgwSender.CancellationPending) return;
                bgwSender.ReportProgress(1, ex);
            }
        }

        

        private void txtQuery_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            TextBox s = (TextBox)sender;
            if (s.Text == "Search")
            {
                s.Text = "";
                s.FontStyle = (FontStyle)new FontStyleConverter().ConvertFromString("Normal");
                s.Foreground = Brushes.Black;
            }
        }

        private void txtQuery_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            TextBox s = (TextBox)sender;
            if (s.Text.Length == 0)
            {
                s.Text = "Search";
                s.FontStyle = (FontStyle)new FontStyleConverter().ConvertFromString("Italic");
                s.Foreground = Brushes.Gray;
            }
        }

        private void menuHelpUpdates_Click(object sender, RoutedEventArgs e)
        {
            App.CheckForUpdates();
        }


        private void winSearch_Closed(object sender, EventArgs e)
        {
            ni.Visible = false;
            Application.Current.Shutdown();
        }

        private void Error_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Exception omgException = new Exception("Whoa its an exception, looks like you're testing out the awesome send error report feature.");
                throw omgException;
            }
            catch (Exception ex)
            {
                App.ShowErrorDialog(ex);
            }
        }

        private void winSearch_StateChanged(object sender, EventArgs e)
        {
            if (Settings.HideWhenMinimized && this.WindowState == WindowState.Minimized)
                Hide();
        }

        private void themeSwitch(object sender, RoutedEventArgs e)
        {
            MenuItem itm = (MenuItem)sender;
            ArmoryViewer.Classes.MkThemeSelector.SetCurrentThemeDictionary(this, new Uri(string.Format("/ArmoryViewer;component/Themes/{0}.xaml", itm.Header.ToString()), UriKind.Relative));
        }
    }
}
